#pragma once

struct DialogText
{
	DialogText() : useUnicode(false)
	{
	}

	std::string szText;
	std::wstring wszText;
	Vertex2F pos;
	bool visible;
	bool useUnicode;
};

extern Texture* borderTex;

template<typename T>
class TextureQuad
{
public:
	TextureQuad() { }
	TextureQuad(ui32 size);
	T* instance;
	void (T::*OnClick)(TextureQuad<T>*);
	std::string szTexture;
	Texture* texture;
	bool textureLoaded;
	Vertex3FRHWT vertices[4];
	Vertex3FRHWT bvertices[4];
	bool visible;
	bool border;
	ui32 m_size;
	void Init()
	{
		if(!borderTex)
			borderTex = CTextureHandler::GetInstance()->GetTexture("Interface\\Buttons\\UI-TempEnchant-Border.blp");
		if(visible && !textureLoaded)
		{
			texture = CTextureHandler::GetInstance()->GetTexture(szTexture);
			textureLoaded = true;
		}
		if(!visible && textureLoaded)
		{
			texture = texture->DecRef();
			textureLoaded = false;
		}
	}
};

class Dialog : public UIElement
{
	Vertex3FRHWT m_baseVertices[4];
	Vertex3FRHWT m_edgeVertices1[4];
	Vertex3FRHWT m_edgeVertices2[4];
	Vertex3FRHWT m_edgeVertices3[4];
	Vertex3FRHWT m_edgeVertices4[4];
	Vertex3FRHWT m_titleVertices[4];
	Vertex3FRHWT m_closeVertices[4];
	Texture* m_baseTexture;
	Texture* m_edgeTexture;
	Texture* m_titleTexture;
	Texture* m_closeTexture;
	Texture* m_cloDownTexture;
	std::vector<Vertex3FRHWT*> m_boxVertices;
	std::set<UIButton<Dialog>*> m_buttons;
	std::set<Checkbox<Dialog>*> m_checkBoxes;
	std::set<EditBox*> m_edits;
	std::set<Scrollbar<Dialog>*> m_scrolls;
	std::set<RadioButton<Dialog>*> m_radios;
	std::set<TextureQuad<Dialog>*> m_quads;
	std::set<VScrollbar<Dialog>*> m_vscrolls;
	std::set<TreeView*> m_trees;
	std::string m_szTitle;
	CFont m_text;
	CFont m_body;
	bool m_moveAble;
	bool m_closeDown;
	bool m_closeBox;
	Vertex2F m_moveLast;
	std::vector<DialogText*> m_bodyText;
public:
	Dialog(ui32 x, ui32 y, ui32 nX, ui32 nY, std::string szTitle = "", bool close = true);
	void Draw();
	bool DialogMouseActivity(bool left, Vertex2F pos, bool up);
	void OnMouseMove(ui32 x, ui32 y, bool lDown, bool rDown);
	template<typename T>
	UIButton<T>* AddButton(T* instance, ui32 x, ui32 w, std::string szText, void (T::*proc)(UIButton<T>*), i32 y = -1, i32 h = -1, i32 texEntry = -1)
	{
		if(y == -1)
		{
			UIButton<T>* pButton = new UIButton<T>(instance, Vertex2F(m_position.x + x, m_position.y + m_size.y - 45), Vertex2F((float)w, (h != -1) ? (float)h : 25), szText, texEntry);
			pButton->SetOnClick(proc);
			m_buttons.insert((UIButton<Dialog>*)pButton);
			return pButton;
		}
		else
		{
			UIButton<T>* pButton = new UIButton<T>(instance, Vertex2F(m_position.x + x, m_position.y + y), Vertex2F((float)w, (h != -1) ? (float)h : 25), szText, texEntry);
			pButton->SetOnClick(proc);
			m_buttons.insert((UIButton<Dialog>*)pButton);
			return pButton;
		}
	}

	template<typename T>
	TextureQuad<T>* AddTexQuad(T* instance, void (T::*Proc)(TextureQuad<T>*), std::string szTexture, Vertex2F pos, ui32 size = 32)
	{
		TextureQuad<T>* quad = new TextureQuad<T>;
		quad->instance = instance;
		quad->OnClick = Proc;
		quad->vertices[0].x = m_position.x + pos.x;
		quad->vertices[0].y = m_position.y + pos.y;
		quad->vertices[0].u = 0.0f;
		quad->vertices[0].v = 0.0f;

		quad->vertices[1].x = m_position.x + pos.x + size;
		quad->vertices[1].y = m_position.y + pos.y;
		quad->vertices[1].u = 1.0f;
		quad->vertices[1].v = 0.0f;

		quad->vertices[2].x = m_position.x + pos.x + size;
		quad->vertices[2].y = m_position.y + pos.y + size;
		quad->vertices[2].u = 1.0f;
		quad->vertices[2].v = 1.0f;

		quad->vertices[3].x = m_position.x + pos.x;
		quad->vertices[3].y = m_position.y + pos.y + size;
		quad->vertices[3].u = 0.0f;
		quad->vertices[3].v = 1.0f;

		memcpy(quad->bvertices, quad->vertices, 4 * sizeof(Vertex3FRHWT));

		quad->bvertices[0].x -= 2;
		quad->bvertices[0].y -= 2;
		quad->bvertices[1].x += 2;
		quad->bvertices[1].y -= 2;
		quad->bvertices[2].x += 2;
		quad->bvertices[2].y += 2;
		quad->bvertices[3].x -= 2;
		quad->bvertices[3].y += 2;

		quad->szTexture = szTexture;
		quad->textureLoaded = false;
		quad->visible = false;
		quad->border = false;
		quad->m_size = size;
		m_quads.insert((TextureQuad<Dialog>*)quad);
		return quad;
	}

	template<typename T>
	void SetQuadPos(TextureQuad<T>* pQuad, ui32 x, ui32 y)
	{
		pQuad->vertices[0].x = m_position.x + x;
		pQuad->vertices[0].y = m_position.y + y;
		pQuad->vertices[1].x = m_position.x + x + 32;
		pQuad->vertices[1].y = m_position.y + y;
		pQuad->vertices[2].x = m_position.x + x + 32;
		pQuad->vertices[2].y = m_position.y + y + 32;
		pQuad->vertices[3].x = m_position.x + x;
		pQuad->vertices[3].y = m_position.y + y + 32;

		memcpy(pQuad->bvertices, pQuad->vertices, 4 * sizeof(Vertex3FRHWT));

		pQuad->bvertices[0].x -= 2;
		pQuad->bvertices[0].y -= 2;
		pQuad->bvertices[1].x += 2;
		pQuad->bvertices[1].y -= 2;
		pQuad->bvertices[2].x += 2;
		pQuad->bvertices[2].y += 2;
		pQuad->bvertices[3].x -= 2;
		pQuad->bvertices[3].y += 2;		
	}

	template<typename T>
	void SetCheckPos(Checkbox<T>* pQuad, ui32 x, ui32 y)
	{
		pQuad->SetPosition(m_position.x + x, m_position.y + y);
	}

	void ResetQuads()
	{
		std::set<TextureQuad<Dialog>*>::iterator itr = m_quads.begin();
		std::set<TextureQuad<Dialog>*>::iterator end = m_quads.end();

		for( ; itr != end; ++itr)
		{
			if((*itr)->textureLoaded && (*itr)->texture)
				(*itr)->texture->DecRef();
			delete (*itr);
		}

		m_quads.clear();
	}

	template<typename T>
	void RemoveQuad(TextureQuad<T>* pQuad)
	{
		if(pQuad->textureLoaded && pQuad->texture)
			pQuad->texture->DecRef();
		delete pQuad;
		m_quads.erase((TextureQuad<Dialog>*)pQuad);
	}

	DialogText* AddText(ui32 x, ui32 y, std::string szText, i32 texEntry = -1)
	{
		DialogText* t = new DialogText();
		t->pos = Vertex2F(m_position.x + x, m_position.y + y);
		t->visible = true;
		t->szText = sLocale.GetLocale(texEntry, szText);
		m_bodyText.push_back(t);
		return t;
	}

	TreeView* AddTreeView(ui32 x, ui32 y, ui32 w, ui32 h)
	{
		TreeView* pTree = new TreeView((ui32)m_position.x + x, (ui32)m_position.y + y, w, h);
		m_trees.insert(pTree);
		return pTree;
	}

	template<typename T>
	Checkbox<T>* AddCheckbox(T* instance, ui32 x, ui32 y, std::string szText, void (T::*pFunc)(Checkbox<T>*, ui32), i32 texEntry = -1)
	{
		Checkbox<T>* box = new Checkbox<T>(instance, ui32(m_position.x + x), ui32(m_position.y + y), 26, 26, szText, texEntry);
		box->SetOnCheckChange(pFunc);
		m_checkBoxes.insert((Checkbox<Dialog>*)box);
		return box;
	}

	EditBox* AddEditBox(ui32 x, ui32 y, ui32 w, ui32 h)
	{
		EditBox* b = new EditBox(ui32(m_position.x + x), ui32(m_position.y + y), w, h);
		m_edits.insert(b);
		sUI.AddEditBox(b);
		return b;
	}

	template<typename T>
	Scrollbar<T>* AddScrollbar(ui32 x, ui32 y, ui32 sizeX, T* instance, typename Scrollbar<T>::ScrollCallback pFunc)
	{
		Scrollbar<T>* pBar = new Scrollbar<T>((ui32)m_position.x + x, (ui32)m_position.y + y, sizeX, instance);
		pBar->SetCallback(pFunc);
		m_scrolls.insert((Scrollbar<Dialog>*)pBar);
		return pBar;
	}

	template<typename T>
	VScrollbar<T>* AddVScrollbar(ui32 x, ui32 y, ui32 sizeX, T* instance, typename VScrollbar<T>::ScrollCallback pFunc)
	{
		VScrollbar<T>* pBar = new VScrollbar<T>((ui32)m_position.x + x, (ui32)m_position.y + y, sizeX, instance);
		pBar->SetCallback(pFunc);
		m_vscrolls.insert((VScrollbar<Dialog>*)pBar);
		return pBar;
	}

	template<typename T>
	RadioButton<T>* AddRadioButton(ui32 x, ui32 y, T* instance, typename RadioButton<T>::CheckChange pFunc)
	{
		RadioButton<T>* pButton = new RadioButton<T>((ui32)m_position.x + x, (ui32)m_position.y + y, instance);
		pButton->SetCallback(pFunc);
		m_radios.insert((RadioButton<Dialog>*)pButton);
		return pButton;
	}

	ui32 GetBodyLength(std::string szText) { return m_body.GetTextLen(szText); }
};